#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>

#define NUM 10

typedef void (*func_t)();//函数指针：类型是void(*)(),将其重命名为func_t

func_t handlerTask[NUM];//函数指针数组---装载函数(任务)

//样例任务
void task1()
{
    printf("handlerTask1\n");
}
void task2()
{
    printf("handlerTask2\n");
}
void task3()
{
    printf("handlerTask3\n");
}

int loadTask(func_t func)
{
    //初始化函数指针数组
    //memset(handlerTask,0,sizeof(handlerTask));
    //handlerTask[0]=task1;
    //handlerTask[1]=task2;
    //handlerTask[2]=task3;
    
    int i=0;
    for(;i<NUM;i++)
    {
        if(handlerTask[i]==NULL) break;
    }
    //找到空，然后加载任务
    if(i==NUM) return -1;//空间已满，加载任务失败，返回-1
    else handlerTask[i]=func;

    //装载成功
    return 0;
}

void InitTask()
{
    int i=0;
    for(i=0;i<NUM;i++) handlerTask[i]=NULL;
    loadTask(task1);
    loadTask(task2);
    loadTask(task3);
}
void RunTask()
{
    int i=0;
    for(i=0;i<NUM;i++)
    {
        if(handlerTask[i]==NULL) continue;
        handlerTask[i]();//运行任务
    }
}
int main()
{
    pid_t id = fork();
    if (id == 0) 
    {
        //child
	    int cnt = 10;
	    while (cnt--)
        {
		  printf("I am child...PID:%d, PPID:%d,cnt:%d\n", getpid(), getppid(),cnt);
		  sleep(1);
	    }
	    exit(10);//自己设置了一个退出码
    }
    InitTask();
    //parent
    //sleep(20);//父进程先不回收子进程，先让我们观察一下子进程的僵尸状态，再回收
    //pid_t ret = wait(NULL);//等待成功返回子进程PID
    int status=0;
    while(1)
    {
        //waitpid会把结果填充到status中
        pid_t ret=waitpid(id,&status,WNOHANG);
        if(ret==0)
        {
            //表示waitpid调用成功，但是子进程还没退出，父进程没有一直在等待，处于非阻塞状态
            //子进程没有退出，waitpid没有等待失败，仅仅是检测到了子进程没有退出，可以多给李四打几次电话，检测他的状态准备好了没有
            printf("wait done, but child is still running......\n");
            //父进程处于非阻塞状态可以做其它事
            RunTask();
            sleep(1);
        }
        else if(ret>0)
        {
            if(WIFEXITED(status))//判断是否异常退出的标准：是否收到终止信号
            {
                printf("wait success,child exit code:%d\n",WEXITSTATUS(status));
            }
            else{
                //获取终止信号
                printf("wait success,child exit signal:%d\n",status&0x7F);
            }
            //waitpid调用成功&&子进程退出了
            //printf("wait success, exit code:%d, sig: %d\n",(status>>8)&0xFF,status&0x7F);
            break;
        }
        else
        {
            //waitpid调用失败
            printf("waitpid call failed\n");
            exit(1);
            break;
        }
    }

    return 0;
    
}
